home *** CD-ROM | disk | FTP | other *** search
- /*
- * int ppopen(char *pgm, FILE **frompgm, FILE **topgm)
- * int ppclose(FILE *fromcmd, FILE *tocmd)
- *
- * Like popen(), but hooks up both input and output FILE pointers to a program.
- * The "program" may be any valid /bin/sh command.
- * ppopen() returns the program's process id if successful, else 0.
- * If successful, ``*frompgm'' and ``*topgm'' are filled in with FILE *'s
- *
- * Take care when using this; deadlock is possible if the program writes a
- * large amount of data (> about 8K bytes) to its output while you're still
- * writing to its input.
- *
- * Typical usage might be:
- * FILE *frompgm, *topgm;
- * ppopen("polymerge", &frompgm, &topgm);
- * GeomFSave(g, topgm, "polymerge");
- * gg = GeomFLoad(frompgm, "polymerged data");
- * ppclose(topgm, frompgm);
- */
-
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <sys/wait.h>
-
- static int npps = 0;
- static unsigned short *pps;
-
- int
- ppopen(char *cmd, FILE **frompgm, FILE **topgm)
- {
- struct pipe { int r, w; } pfrom, pto;
- int i, pid;
-
-
- /* create the communication pipes */
- pfrom.r = pfrom.w = -1;
- if(pipe(&pfrom) < 0 || pipe(&pto) < 0) {
- perror("Can't make pipe");
- close(pfrom.r); close(pfrom.w);
- return 0;
- }
-
- switch(pid = fork()) {
- case -1:
- perror("Can't fork");
- return 0;
-
- case 0: {
- static char rats[] = "Can't exec external module: ";
- close(pfrom.r);
- close(pto.w);
- dup2(pto.r, 0);
- dup2(pfrom.w, 1);
- execl("/bin/sh", "sh", "-c", cmd, NULL);
-
- write(2, rats, sizeof(rats)-1);
- perror(cmd);
- exit(1);
- }
- }
-
- close(pto.r);
- close(pfrom.w);
- *frompgm = fdopen(pfrom.r, "r");
- *topgm = fdopen(pto.w, "w");
- if(pfrom.r < npps) {
- int newsize = (pfrom.r + 10)*sizeof(pps[0]);
- npps = pfrom.r + 10;
- pps = (unsigned short *) (pps ? realloc(pps, newsize) : malloc(newsize));
- bzero(&pps[npps], newsize - npps*sizeof(pps[0]));
- pps[pfrom.r] = pid;
- }
- return pid;
- }
-
- ppclose(FILE *frompgm, FILE *topgm)
- {
- union wait w;
- unsigned int fd;
- int pid;
-
- if(frompgm == NULL) return -1;
- if(topgm) fclose(topgm);
- fd = fileno(frompgm);
- fclose(frompgm);
- if(fd < npps && pps[fd] != 0) {
- pps[fd] = 0;
- while((pid = wait(&w)) != pps[fd] && pid > 0)
- ;
- }
- }
-